﻿namespace CodeBetter.Extensions.Tests
{
   using NUnit.Framework;
   using System.Globalization;
   
   [TestFixture]
   public class StringParserTests
   {
      [Test]
      public void ToInt()
      {
         Assert.AreEqual(1234, "1234".ToInt());
         Assert.AreEqual(-1234, "-1234".ToInt());
      }
      [Test, ExpectedException("System.FormatException")]
      public void ToInt_ThrowsExceptionForInvalidFormat()
      {
         "a1234".ToInt();
         Assert.Fail();
      }
      [Test]
      public void ToInt_ReturnsParsedValueEvenWithDefault()
      {
          Assert.AreEqual(123, "123".ToInt(0));
      }
      [Test]
      public void ToInt_ReturnsDefaultValueForInvalidForamt()
      {
          Assert.AreEqual(0, "a123".ToInt(0));
      }
      
      [Test]
      public void ToBoolean()
      {
         Assert.IsTrue("1".ToBoolean());
         Assert.IsTrue("true".ToBoolean());
         Assert.IsFalse("0".ToBoolean());
         Assert.IsFalse("false".ToBoolean());
      }
      [Test, ExpectedException("System.FormatException")]
      public void ToBoolean_ThrowsExceptionForInvalidFormat()
      {
         "nose".ToBoolean();
         Assert.Fail();
      }
      [Test]
      public void ToBoolean_ReturnsParsedValueEvenWithDefault()
      {
          Assert.AreEqual(true, "true".ToBoolean(false));
      }
      [Test]
      public void ToBoolean_ReturnsDefaultValueForInvalidForamt()
      {
          Assert.AreEqual(false, "a123".ToBoolean(false));
      }
      
      [Test]
      public void ExtractInt_ReturnsPositiveIntegers()
      {
         Assert.AreEqual(1, "1".ExtractInt());
         Assert.AreEqual(1, "1a".ExtractInt());
         Assert.AreEqual(234, " 234abbk399a".ExtractInt());
      }
      [Test]
      public void ExtractInt_ReturnsNegativeIntegers()
      {
         Assert.AreEqual(-1, "-1".ExtractInt());
         Assert.AreEqual(-1, "-1a".ExtractInt());
         Assert.AreEqual(-234, " -234abbk399a".ExtractInt());
      }
      [Test, ExpectedException("System.FormatException")]
      public void ExtractInt_ThrowsExceptionIfUnableToExtractFromEmptyString()
      {
         "".ExtractInt();
         Assert.Fail();
      }
      [Test, ExpectedException("System.FormatException")]
      public void ExtractInt_ThrowsExceptionIfUnableToExtractFromNegativeSign()
      {
         "-".ExtractInt();
         Assert.Fail();
      }
      [Test, ExpectedException("System.FormatException")]
      public void ExtractInt_ThrowsExceptionIfUnableToExtractFromWord()
      {
         "two".ExtractInt();
         Assert.Fail();
      }
      [Test]
      public void TryExtractInt_ReturnsTrueOnSuccess()
      {
         int x;
         Assert.IsTrue("-3233".TryExtractInt(out x));
         Assert.AreEqual(-3233, x);
      }
      [Test]
      public void TryExtractInt_ReturnsFalseOnFailure()
      {
         int x;
         Assert.IsFalse("-af3233".TryExtractInt(out x));         
      }

      [Test]
      public void ToDouble()
      {
         Assert.AreEqual(9000.1d, ("9000" + CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator + "1").ToDouble());
         Assert.AreEqual(-9000.1d, ("-9000" + CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator + "1").ToDouble());
      }
      [Test, ExpectedException("System.FormatException")]
      public void ToDouble_ThrowsExceptionForInvalidFormat()
      {
         "19h000.1".ToDouble();
         Assert.Fail();
      }
      public void ToDouble_ReturnsParsedValueEvenWithDefault()
      {
          Assert.AreEqual(123, "123".ToDouble(0));
      }
      [Test]
      public void ToDouble_ReturnsDefaultValueForInvalidForamt()
      {
          Assert.AreEqual(0, "a123".ToDouble(0));
      }

      [Test]
      public void ToFloat()
      {
         Assert.AreEqual(9000.1f, ("9000" + CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator + "1").ToFloat());
         Assert.AreEqual(-9000.1f, ("-9000" + CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator + "1").ToFloat());
      }
      [Test, ExpectedException("System.FormatException")]
      public void ToFloat_ThrowsExceptionForInvalidFormat()
      {
         "19h000.1".ToFloat();
         Assert.Fail();
      }
      public void ToFloat_ReturnsParsedValueEvenWithDefault()
      {
          Assert.AreEqual(123, "123".ToFloat(0));
      }
      [Test]
      public void ToFloat_ReturnsDefaultValueForInvalidForamt()
      {
          Assert.AreEqual(0, "a123".ToFloat(0));
      }

      [Test]
      public void ToEnum_ParseStringRepresentation()
      {
          Assert.AreEqual(SampleEnum.One, "one".ToEnum<SampleEnum>());
          Assert.AreEqual(SampleEnum.Two, "Two".ToEnum<SampleEnum>());
      }
      [Test]
      public void ToEnum_ParseIntegerRepresentation()
      {
          Assert.AreEqual(SampleEnum.One, "1".ToEnum<SampleEnum>());
          Assert.AreEqual(SampleEnum.Two, "2".ToEnum<SampleEnum>());
      }
      [Test, ExpectedException("System.ArgumentException")]
      public void ToEnum_ThrowsExceptionForUnknownInt()
      {
          "85".ToEnum<SampleEnum>();       
      }
      [Test, ExpectedException("System.ArgumentException")]
      public void ToEnum_ThrowsExceptionForUnknownString()
      {
          "abc".ToEnum<SampleEnum>();
      }
      [Test]
      public void ToEnum_ReturnsParsedValueEvenWithDefault()
      {
          Assert.AreEqual(SampleEnum.Two, "Two".ToEnum(SampleEnum.One));
      }
      [Test]
      public void ToEnum_ReturnsDefaultValueOnInvalidFormat()
      {
          Assert.AreEqual(SampleEnum.One, "five".ToEnum<SampleEnum>(SampleEnum.One));
      }

      [Test]
      public void ToEnum_ReturnsDefaultValueOnUnknownValue()
      {
          Assert.AreEqual(SampleEnum.One, "54".ToEnum(SampleEnum.One));
      }
   }

   public enum SampleEnum
   {
       Zero = 0,
       One = 1,
       Two = 2,
       Three = 3,
   }
}
